package com.zlzlib.libscan;

import android.content.Context;
import android.graphics.Bitmap;
import android.hardware.Camera;
import android.os.AsyncTask;
import android.os.Handler;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.widget.FrameLayout;



/**
 * Created by zlz on 2018/9/13.
 * 扫描控件
 */
public abstract class BaseScanView extends FrameLayout implements Camera.PreviewCallback {
    //摄像头
    protected Camera mCamera;
    protected int mCameraId = Camera.CameraInfo.CAMERA_FACING_BACK;
    protected Handler mHandler;
    //是否停止识别
    protected boolean spotAble = false;
    //照相的页面
    private ScanCameraView cameraView;
    protected ResultListener resultListener;
    private BaseProcessTask task;
    protected MyScanBoxView scanBox;

    public BaseScanView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initView(context, attrs);
    }

    private void initView(Context context, AttributeSet attrs) {
        mHandler = new Handler();
        cameraView = new ScanCameraView(context, attrs);
        //添加拍摄显示的画面
        addView(cameraView);
        //添加扫码框
        scanBox = new MyScanBoxView(context, attrs);
        addView(scanBox);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    @Override
    public void onPreviewFrame(byte[] data, Camera camera) {
        //相机拍出来每一帧的数据
        if (!spotAble || (task != null && (task.getStatus() == AsyncTask.Status.PENDING || task.getStatus() == AsyncTask.Status.RUNNING))) {
            return;
        }
        //后台线程解析
        task = new BaseProcessTask(camera, this, data, Utils.isPortrait(getContext())).perform();
    }

    public void onStartCamera() {
        startCamera(mCameraId, 500);
    }

    public void onStopCamera() {
        stopCamera();
    }

    public void onDestroyCamera() {
        stopCamera();
        mHandler = null;
        resultListener = null;
        previewCallbackTask = null;
    }

    /**
     * 打开指定摄像头开始预览，但是并未开始识别
     */
    public void startCamera(int cameraFacing, int delay) {
        if (mCamera != null) {
            return;
        }
        Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
        for (int cameraId = 0; cameraId < Camera.getNumberOfCameras(); cameraId++) {
            Camera.getCameraInfo(cameraId, cameraInfo);
            if (cameraInfo.facing == cameraFacing) {
                startCameraById(cameraId, delay);
                break;
            }
        }
    }

    private void startCameraById(int cameraId, final int delay) {
        try {
            mCameraId = cameraId;
            mCamera = Camera.open(cameraId);
            cameraView.setCamera(mCamera, new ScanCameraView.FocusSuccessListener() {
                @Override
                public void success() {
                    //开始识别
                    startSpotDelay(delay);
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
            //摄像头开启失败
            if (null != resultListener) resultListener.onScanOpenCameraError();
        }
    }

    /**
     * 关闭摄像头预览，并且隐藏扫描框
     */
    private void stopCamera() {
        try {
            stopSpot();
            if (mCamera != null) {
                cameraView.stopCameraPreview();
                cameraView.setCamera(null, null);
                mCamera.release();
                mCamera = null;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 停止识别
     */
    private void stopSpot() {
        spotAble = false;
        //关闭后台识别的线程
        if (task != null) {
            task.cancelTask();
            task = null;
        }
        if (mCamera != null) {
            try {
                mCamera.setOneShotPreviewCallback(null);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        if (mHandler != null) {
            mHandler.removeCallbacks(previewCallbackTask);
        }
    }

    /**
     * 延迟delay毫秒后开始识别
     */
    private void startSpotDelay(int delay) {
        spotAble = true;
        // 开始前先移除之前的任务
        if (mHandler != null) {
            mHandler.removeCallbacks(previewCallbackTask);
            mHandler.postDelayed(previewCallbackTask, delay);
        }
    }

    private Runnable previewCallbackTask = new Runnable() {
        @Override
        public void run() {
            if (mCamera != null && spotAble) {
                try {
                    mCamera.setOneShotPreviewCallback(BaseScanView.this);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    };

    public void setResultListener(ResultListener listener) {
        this.resultListener = listener;
    }

    public interface ResultListener {
        /**
         * 处理扫描结果
         *
         * @param result
         */
        void onScanSuccess(String result);

        /**
         * 处理打开相机出错
         */
        void onScanOpenCameraError();
    }

    //处理图片识别结果  异步
    protected abstract ScanResult processBitmapData(Bitmap bitmap);

    //处理扫描结果 异步
    protected abstract ScanResult processData(byte[] data, int width, int height, boolean isRetry);

    protected void onPostData(ScanResult scanResult) {
        if (!spotAble) {
            return;
        }
        String result = scanResult == null ? null : scanResult.result;
        if (TextUtils.isEmpty(result)) {
            try {
                if (mCamera != null) {
                    mCamera.setOneShotPreviewCallback(this);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        } else {
            try {
                if (resultListener != null) {
                    resultListener.onScanSuccess(result);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    protected void onPostBitmapOrPicture(ScanResult scanResult) {
        if (resultListener != null) {
            String result = scanResult == null ? null : scanResult.result;
            resultListener.onScanSuccess(result);
        }
    }

    /**
     * 解析本地图片二维码。返回二维码图片里的内容 或 null
     *
     * @param picturePath 要解析的二维码图片本地路径
     */
    public void decodeQRCode(String picturePath) {
        task = new BaseProcessTask(this, picturePath).perform();
    }

    /**
     * 解析 Bitmap 二维码。返回二维码图片里的内容 或 null
     *
     * @param bitmap 要解析的二维码图片
     */
    public void decodeQRCode(Bitmap bitmap) {
        task = new BaseProcessTask(this, bitmap).perform();
    }

    public void openFlashLight() {
        cameraView.openFlashlight();
    }

    public void closeFlashLight() {
        cameraView.closeFlashlight();
    }

    public MyScanBoxView getScanBox() {
        return scanBox;
    }

}
